/*
 * Copyright (C) 2012 mAPPn.Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mol.market.demo.widget;

import junit.framework.AssertionFailedError;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.actionbarsherlock.app.SherlockFragment;
import com.mol.market.common.util.Utils;

/**
 * @Description              类继承结构图
 * 
 *                       {@link BaseFragment} (最顶层的Fragment)
 *                                |
 *                                |
 *                    {@link BaseFragmentWrapper}
 *                                |
 *                - - - - - - - - - - - - - - - - - -
 *               |                                   |
 *    {@link AbsTabFragment}             {@link AbsListViewFragment}        
 *               |                                   |
 *       {@link TabWrapper}            - - - - - - - - - - - - - - - - - -   
 *                                    |                                   |
 *                    {@link LazyLoadAbsListViewFragment}    {@link ListFragmentWrapper} 
 *                                    |
 *                       {@link LazyLoadListFragment}   ---------->  UI实现层
 *                                    |
 *                    - - - - - - - - - - - - - - - - - -
 *                   |                                   |
 *  {@link LazyLoadFragmentWrapper}     {@link SimpleLazyLoadFragmentLoader}    ---------->  业务逻辑API实现层
 */


/**
 * 最基础的Fragment<hr>
 * 作为Fragment，必须要创建三个View用来应对横屏和竖屏以及未知的情况。
 * <br>
 * {@link #onCreateViewLand(LayoutInflater, ViewGroup, Bundle)} and
 * {@link #onCreateViewPort(LayoutInflater, ViewGroup, Bundle)} and
 * {@link #onCreateViewUndefined(LayoutInflater, ViewGroup, Bundle)}
 * @author Chaos	
 * @date 2012-12-12 
 */
public abstract class BaseFragment extends SherlockFragment{
    
    private static DisplayMetrics mScreenSize = new DisplayMetrics();
    /**
     * 屏幕方向
     */
    private static Orientation mOrientation = Orientation.UNINITIALIZED;
    
    /**
     * Fragment必须持有默认构造器
     */
    public BaseFragment(){ 
        
    }
    
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        
        if (openOrientationMonitor()) {
            Orientation newOri = getOriIfNeed();
            if (mOrientation != newOri) {
                // 如果方向不同，触发改变。
                onOrientationChange(mOrientation, newOri);
                updateOrientation(newOri);
            }
        }
    }
    
    @Override
    public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        switch (mOrientation) {
        case LAND:
            return onCreateViewLand(inflater, container, savedInstanceState);
        case PORT:
            return onCreateViewPort(inflater, container, savedInstanceState);
        case UNINITIALIZED:
            return onCreateViewUndefined(inflater, container, savedInstanceState);
        default:
            throw new AssertionFailedError("unknown error");
        }
    }
    
    public final Orientation getOrientation(){
        return mOrientation;
    }
    
    /**
     * 是否为横屏
     */
    public final boolean isLand() {
        return mOrientation == Orientation.LAND;
    }
    
    /**
     * 是否为竖屏
     */
    public final boolean isPort(){
        return mOrientation == Orientation.PORT;
    }
    
    /**
     * 屏幕宽度pix
     */
    public final int getWidth(){
        return mScreenSize.widthPixels;
    }
    
    /**
     * 屏幕高度pix
     */
    public final int getHeight(){
        return mScreenSize.heightPixels;
    }
    
    /**
     * 返回屏幕宽度，单位dip
     */
    public final int getWidthDp(){
        return (int) (getWidth()/mScreenSize.density);
    }
    
    /**
     * 返回屏幕宽度，单位dip
     */
    public final int getHeightDp(){
        return (int) (getHeight()/mScreenSize.density);
    }
    
    /**
     * The logical density of the display.  This is a scaling factor for the
     * Density Independent Pixel unit, where one DIP is one pixel on an
     * approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen), 
     * providing the baseline of the system's display. Thus on a 160dpi screen 
     * this density value will be 1; on a 120 dpi screen it would be .75; etc.
     *  
     * <p>This value does not exactly follow the real screen size (as given by 
     * {@link DisplayMetrics#xdpi} and {@link DisplayMetrics#ydpi}, but rather is used to scale the size of
     * the overall UI in steps based on gross changes in the display dpi.  For 
     * example, a 240x320 screen will have a density of 1 even if its width is 
     * 1.8", 1.3", etc. However, if the screen resolution is increased to 
     * 320x480 but the screen size remained 1.5"x2" then the density would be 
     * increased (probably to 1.5).
     *
     * @see #DENSITY_DEFAULT
     */
    public final float getDensity(){
        return mScreenSize.density;
    }
    
    /**
     * The screen density expressed as dots-per-inch.  May be either
     * {@link DisplayMetrics#DENSITY_LOW}, 
     * {@link DisplayMetrics#DENSITY_MEDIUM}, or {@link DisplayMetrics#DENSITY_HIGH}.
     */
    public final int getDPI(){
        return mScreenSize.densityDpi;
    }
    
    /**
     * FIXME 目前没有达到IfNeed的功能，每个Fragment的子类都会去更新屏幕信息。也许会消耗不必要的性能。
     *       暂时还没有想到更好的方法。
     *       by Chaos at 2013/1/14
     */
    private Orientation getOriIfNeed(){
        setup();
        return mScreenSize.widthPixels > mScreenSize.heightPixels ? Orientation.LAND
                : Orientation.PORT;
    }
    
    /**
     * 更新DisplayMetrics的信息
     */
    private void setup(){
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(mScreenSize);
    }
    
    private void updateOrientation(Orientation newOri){
        mOrientation = newOri;
    }
    
    public final Context getApplicationContext(){
        return getActivity().getApplicationContext();
    }
    
    /**
     * Fragment的方向发生了改变，调用在{@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}之前.
     * @param 
     */
    protected abstract void onOrientationChange(Orientation oldOri,Orientation newOri);      
  
    
    /**
     * 宽大于高时，需要展示的界面。
     */
    protected abstract View onCreateViewLand(LayoutInflater inflater, 
            ViewGroup container, Bundle savedInstanceState);
    
    /**
     * 宽小于高时，需要展示的界面。
     */
    protected abstract View onCreateViewPort(LayoutInflater inflater, 
            ViewGroup container, Bundle savedInstanceState);
    
    /**
     * 当无法获取屏幕的宽高时，将会调用此方法创建View并显示。
     * <hr>
     * 当因为未知原因无法获取宽高时，或者{@link #openOrientationMonitor()}的返回值为false时，
     * 将会调用此方法。
     */
    protected abstract View onCreateViewUndefined(LayoutInflater inflater, 
            ViewGroup container, Bundle savedInstanceState);
    
    /**
     * 当Fragment销毁时，其成员变量还未被及时销毁，因此我们需要手动置为空，加快其回收速度。
     * <br>
     * 调用此方法清除全局变量
     */
    protected void dealloc(){
    };
    
    @Override
    public void onStop() {
        super.onStop();
    }
    
    @Override
    public void onDestroy() {
        dealloc();
        
        Utils.I(String.format("The class : '%s' will be destroy after dealloc", getClass().getName().toString()));
        
        super.onDestroy();
    }
    
    /**
     * 是否进行横竖屏监听.
     * <hr>
     * 如果返回<strong>false</strong>，此类中所有get方法的返回值<strong><em> 将不会再被更新 </em></strong>
     */
    protected boolean openOrientationMonitor(){
        return true;
    }
    
//    /**
//     * 跳转到目标的Fragment
//     */
//    public boolean gotoTargetFragment(Class<? extends Fragment> target,Bundle args,boolean addBackStack){
//        
//        FragmentManager fm = getFragmentManager();
//        
//        Fragment entity = fm.findFragmentByTag(target.getName());
//        if(entity == null){
//            entity = Fragment.instantiate(getApplicationContext(), target.getName());
//            
//            if(args != null){
//                entity.setArguments(args);
//            }
//            
//            System.out.println("create instantitate!");
//        }
//        
//        FragmentTransaction ft = fm.beginTransaction();
//        
//        ft.add(entity, target.getName());
//        
//        return false;
//    }
    
    /**
     * 屏幕方向
     * @author Chaos	
     * @date 2012-12-12
     */
    public enum Orientation{
        /**
         * 横屏
         */
        LAND,
        /**
         * 竖屏
         */
        PORT,
        /**
         * 未初始化，第一次进入页面。
         */
        UNINITIALIZED;
    }
    
}
